#include "precomp.hpp"
#pragma warning(disable : 4996)
HINSTANCE g_hinst;
LPWSTR g_classname = L"Dict_Baidu";
LRESULT CALLBACK wndproc(HWND, UINT, WPARAM, LPARAM);
void translate(wstring &req,string & result,char* to_lang);

ATOM regClass(HINSTANCE hInst) {
	WNDCLASSEX wcex;
	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS| CS_SAVEBITS|CS_OWNDC;
	wcex.lpfnWndProc = wndproc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = hInst;
	wcex.hIcon = NULL;
	wcex.hCursor = LoadCursor(nullptr,IDC_ARROW);
	wcex.hbrBackground = HBRUSH(COLOR_INFOBK+1);
	wcex.lpszMenuName = NULL;
	wcex.lpszClassName = g_classname;
	wcex.hIconSm = NULL;
	return RegisterClassEx(&wcex);
}

BOOL initInst(HINSTANCE hinst, int cmdshow) {
	g_hinst = hinst;
	HWND hWnd = CreateWindowEx(WS_EX_TOPMOST ,
		g_classname, NULL, WS_POPUP,
		100, 100, 450, 256, NULL, NULL, hinst, NULL);
	if (!hWnd)
		return false;
	UpdateWindow(hWnd);

	return true;
}
int APIENTRY wWinMain(_In_ HINSTANCE hinst,	HINSTANCE hpreInst,	LPWSTR lpcmdline,int ncmdsow)
{
	UNREFERENCED_PARAMETER(hpreInst);
	UNREFERENCED_PARAMETER(lpcmdline);
	regClass(hinst);
	if (!initInst(hinst, ncmdsow))
		return false;
	MSG msg;
	while (GetMessage(&msg, nullptr, 0, 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return (int)msg.wParam;
}


LRESULT CALLBACK wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
	static wstring wbuf;
	static string result;
	static RECT r;
	static UINT_PTR idTimer;
	switch (msg)
	{
	case WM_LBUTTONDOWN:
		PostMessage(hwnd,WM_NCLBUTTONDOWN, HTCAPTION, lparam);
		break;
	case WM_TIMER:
		KillTimer(hwnd, idTimer);
		idTimer = 0;
		ShowWindow(hwnd, SW_HIDE);
		break;
	case WM_CREATE:
		startCatch(hwnd);
		wbuf.reserve(4 * 1024);
		result.reserve(4 * 1024);
		break;
	case WM_DRAWCLIPBOARD:
		if (OpenClipboard(NULL)) {
			HGLOBAL hMem = GetClipboardData(CF_UNICODETEXT);
			if (NULL != hMem) {
				LPCWSTR lpstr = (LPCWSTR)(GlobalLock(hMem));
				if (NULL != lpstr){
					int zh_cnt=0;
					wbuf = lpstr;
					GlobalUnlock(hMem);
					CloseClipboard();
					if (wbuf.size() > 2048) break;
					for (unsigned int i = 0; i < wbuf.size(); i++){
						if (wbuf[i] == 0xa0) wbuf[i] = 0x20;
						if (wbuf[i] >= 0x4e00 && wbuf[i] <= 0x9fa5) zh_cnt++;
					}
					if (zh_cnt>(int)(wbuf.size()>>1))
						translate(wbuf, result, "en");
					else
						translate(wbuf, result,"zh");
					Beep(3000, 200);
					{
						HDC dc = GetDC(hwnd);
						int x, y;
						GetClientRect(hwnd, &r);
						DrawText(dc, wbuf.c_str(), (int)wbuf.length(), &r, DT_CALCRECT );
						if (r.right > 640) {
							r.right = 640;
							DrawText(dc, wbuf.c_str(), (int)wbuf.length(), &r, DT_CALCRECT|  DT_WORDBREAK);
						}
						ReleaseDC(hwnd, dc);
						r.right += 40, r.bottom += 20;

						POINT p;
						RECT rs;
						GetClientRect(GetDesktopWindow(),&rs);
						GetCursorPos(&p);
						x = p.x + r.right > rs.right ? rs.right - r.right : p.x;
						y = p.y + r.bottom > rs.bottom-10 ? p.y - r.bottom - 10 : p.y + 10;
						InvalidateRect(hwnd, NULL, true);
						SetWindowPos(hwnd, HWND_TOP, x, y, r.right, r.bottom, SWP_SHOWWINDOW| SWP_NOACTIVATE);
						idTimer = SetTimer(hwnd, idTimer, (wbuf.size()/7+1) *1000, NULL);
					}
					break;
				}
				GlobalUnlock(hMem);
				CloseClipboard();
				break;
			}
			CloseClipboard();
		}
		break;
	case WM_RBUTTONUP:
		ShowWindow(hwnd, SW_HIDE);
		if (idTimer)KillTimer(hwnd, idTimer);
		break;
	case WM_PAINT:
	{
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hwnd, &ps);
		SetBkMode(hdc, TRANSPARENT);
		InflateRect(&r, -20, -10);
		DrawText(hdc, wbuf.c_str(), (int)wbuf.length(), &r,   DT_WORDBREAK);
		EndPaint(hwnd, &ps);
	}
		break;
	case WM_DESTROY:
		stopCatch();
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hwnd, msg, wparam, lparam);
	}
	return 0;
}







string getSign(string &aid, string & pwd, string &req, string & rnd) {
	static string buf;
	buf.clear();
	buf= aid + req + rnd + pwd;
	string rtn(32, 0);
	UCHAR mdbuf[16];
	MD5((const UCHAR*)buf.c_str(), buf.length(), mdbuf);

	for (int i = 0; i < 16; i++) {
		sprintf(&rtn[i << 1], "%2.2x", mdbuf[i]);
	};
	return rtn;
}
bool init(string &aid, string &pwd) {
	TCHAR path[MAX_PATH];
	size_t ln = (size_t)GetCurrentDirectory(MAX_PATH, path);
	wcscat(path, L"\\config.dat");
	ifstream fc(path);
	if (!fc.is_open()) return false;
	fc.getline(&aid[0], aid.length());
	aid.resize(fc.eof() ? (unsigned int)fc.gcount() : (unsigned int)fc.gcount() - 1);

	fc.getline(&pwd[0], pwd.length());
	pwd.resize(fc.eof() ? (unsigned int)fc.gcount() : (unsigned int)fc.gcount() - 1);
	return aid.length() > 0 && pwd.length() > 0;
}

void w2m(wstring & req, string &dst) {
	size_t x;
	dst.resize(4096);
	x = WideCharToMultiByte(CP_UTF8, 0, req.c_str(), (int)req.length(), &dst[0], (int)dst.capacity(), NULL, false);
	dst.resize(x);
}

size_t write_callback(char *ptr, size_t size, size_t nmemb, string&userdata) {
	userdata.append(ptr, (size_t)size*nmemb);
	return size*nmemb;
}
void baiduapi(string &req, string &aid, string &pwd,char* to_lang)
{
	const static char *orgUrl = "http://api.fanyi.baidu.com/api/trans/vip/translate?";
	char buf[10];
	string rnd = itoa(rand(), buf, 10);
	string sign = getSign(aid, pwd, req, rnd);

	CURL *curl = curl_easy_init();
	static string _req;
	_req.clear();
	char*p= curl_escape(req.c_str(), (int)req.length());
	_req = p;
	static string url;
	url = orgUrl;
	url += "q=" + _req + "&from=auto&to=" + to_lang + "&appid=" + aid + "&salt=" + rnd + "&sign=" + sign;
	curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
	req.clear();
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, &req);
	CURLcode res = curl_easy_perform(curl);
	curl_easy_cleanup(curl);
}
void formatresult(wstring &dst, string &src) {
	dst.clear();
	dst.resize(src.length()*2);
	char *p = &src[0];
	wchar_t *d = &dst[0];
	for (; *p;) {
		if (*p=='\\') {
			if ((*(p + 1)) == 'u') {
				char b;
				char *c;
				p += 2;
				b = *(p + 4);
				*(p + 4) = 0;
				*d++ = (wchar_t)strtol(p, &c, 16);
				*(p + 4) = b;
				p = c;
				continue;
			}
		}
		*d++ = *p++;
	}
	dst.resize((d - &dst[0]));
}
void translate(wstring & req, string &result,char* to_lang)
{
	static string aid(32, 0);
	static string pwd(32, 0);

	static bool inited = false;
	if (!inited) inited = init(aid, pwd);
	if (!inited) return;
	 w2m(req,result);
	 baiduapi(result, aid, pwd,to_lang);
	 static string buf;
	 buf.clear();
	 size_t size = result.size();
	 for (unsigned int i =(int)result.find("dst\":\"", 0); i<size; i= (int)result.find("dst\":\"", i))
	 {
		 i += 6;
		 size_t pos = result.find("\"}", i);
		 if (pos<size)
		 {
			 buf.append(result.substr(i, pos-i));
			 buf.append("\r\n");
		 }
		 i = (int)pos;
	 }
	 formatresult(req, buf);
}